//
// Created by cmj on 2020/7/21.
//
#include <erlua_error.h>
#include <iostream>

struct ERLUA_GLOBAL erlua_global;

//#define ERLUA_INIT_ATOM(env, name) erlua_atoms.name = enif_make_atom( env, #name )
void erlua_init_global(ErlNifEnv *caller_env) {
    erlua_global.ok = enif_make_atom(caller_env, "ok");
    erlua_global.nil = enif_make_atom(caller_env, "nil");
    erlua_global.atom_true = enif_make_atom(caller_env, "true");
    erlua_global.atom_false = enif_make_atom(caller_env, "false");
    erlua_global.error = enif_make_atom(caller_env, "error");
    erlua_global.exception = enif_make_atom(caller_env, "exception");
    erlua_global.wrong_args_nums = enif_make_atom(caller_env, "wrong_args_nums");
    erlua_global.not_lua_state = enif_make_atom(caller_env, "not_lua_state");
    erlua_global.allocation_fail = enif_make_atom(caller_env, "allocation_fail");
    erlua_global.runtime_error = enif_make_atom(caller_env, "runtime_error");
    erlua_global.syntax_error = enif_make_atom(caller_env, "syntax_error");
    erlua_global.gc_error = enif_make_atom(caller_env, "gc_error");
    erlua_global.msgh_error = enif_make_atom(caller_env, "msgh_error");
    erlua_global.yield = enif_make_atom(caller_env, "yield");
    erlua_global.cannot_open = enif_make_atom(caller_env, "cannot_open");
    erlua_global.unknown = enif_make_atom(caller_env, "unknown");
}

ERL_NIF_TERM erlua_ecode(decltype(LUA_OK) ecode) {
    switch (ecode) {
        case LUA_OK:
            return erlua_global.ok;
        case LUA_YIELD:
            return erlua_global.yield;
        case LUA_ERRRUN:
            return erlua_global.runtime_error;
        case LUA_ERRSYNTAX:
            return erlua_global.syntax_error;
        case LUA_ERRMEM:
            return erlua_global.allocation_fail;
        case LUA_ERRGCMM:
            return erlua_global.gc_error;
        case LUA_ERRERR:
            return erlua_global.msgh_error;
        case LUA_ERRFILE:
            return erlua_global.cannot_open;
        default:
            return erlua_global.unknown;
    }
}

void erlua_dump_stack(lua_State *L, char const *file, int line) {
    int i;
    int top = lua_gettop(L);
    std::cout << "lua stack file:" << file << " line:" << line << "----\n";
    for (i = 1; i <= top; i++) {  /* repeat for each level */
        int t = lua_type(L, i);
        switch (t) {
            case LUA_TSTRING:  /* strings */
                std::cout << i << ":" << lua_tostring(L, i) << '\n';
                break;
            case LUA_TBOOLEAN:  /* booleans */
                std::cout << i << ":" << (lua_toboolean(L, i) ? "true" : "false") << '\n';
                break;
            case LUA_TNUMBER:  /* numbers */
                std::cout << i << ":" << lua_tonumber(L, i) << '\n';
                break;
            default:  /* other values */
                std::cout << i << ":" << lua_typename(L, t) << '\n';
                break;
        }
    }
    std::cout << std::endl; /* end the listing */
}
